{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "35c773c5-584d-4d6e-9fee-fa207133b4d9",
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import datetime\n",
    "import torch\n",
    "import torchvision"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "8f33de1f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "cuda\n"
     ]
    }
   ],
   "source": [
    "\n",
    "\n",
    "device=torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n",
    "print(device)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "4d7e27e7-77d8-4238-9826-77be3eab8a29",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "/home/jimmy/code/AI/aiproject-learn/vae\n"
     ]
    }
   ],
   "source": [
    "\n",
    "print(os.getcwd())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "13fec761-2d9d-4a0c-9b9b-f3d0476ac170",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "784"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "28 * 28"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "78c6db0c",
   "metadata": {},
   "source": [
    "数据集"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "2435c285",
   "metadata": {},
   "outputs": [],
   "source": [
    "transform=torchvision.transforms.Compose([\n",
    "    torchvision.transforms.ToTensor(),\n",
    "])\n",
    "dataset=torchvision.datasets.mnist.MNIST(root='~/code/AI/data-set/MNIST',train=True,download=True,transform=transform)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "763b7050",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "img=torch.Size([1, 28, 28]) label=5\n"
     ]
    }
   ],
   "source": [
    "img,label=dataset[0]\n",
    "print(f'img={img.shape} label={label}')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b414335f",
   "metadata": {},
   "source": [
    "模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "14a2e7c8",
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "from torch.nn import functional as F\n",
    "\n",
    "class VAE(torch.nn.Module):\n",
    "    def __init__(self,input_size,hidden_size,latent_size):\n",
    "        super().__init__()\n",
    "        \n",
    "        self.fc1=torch.nn.Linear(in_features=input_size,out_features=hidden_size)\n",
    "        self.fc_mu=torch.nn.Linear(in_features=hidden_size,out_features=latent_size)\n",
    "        self.fc_logvar=torch.nn.Linear(in_features=hidden_size,out_features=latent_size)\n",
    "        \n",
    "        self.fc2=torch.nn.Linear(in_features=latent_size,out_features=hidden_size)\n",
    "        self.fc3=torch.nn.Linear(in_features=hidden_size,out_features=input_size)\n",
    "    \n",
    "    def reparameterize(self,mu,logvar):\n",
    "        '''\n",
    "        计算标准差std\n",
    "        1、log_var * 0.5 相当于 log(方差) * 0.5\n",
    "        2、根据对数性质log(a^n) = n * log(a)，这等于 log(方差^(1/2))\n",
    "        '''\n",
    "        std=torch.exp(logvar*0.5)\n",
    "        eps=torch.randn_like(mu)\n",
    "        return mu+eps*std\n",
    "    \n",
    "    def forward(self,x):\n",
    "        hidden=F.relu(self.fc1(x.view(x.size(0),-1)))\n",
    "        mu=self.fc_mu(hidden)\n",
    "        logvar=self.fc_logvar(hidden)\n",
    "        \n",
    "        z=self.reparameterize(mu,logvar)\n",
    "        \n",
    "        recon_x=F.relu(self.fc2(z))\n",
    "        recon_x=self.fc3(recon_x)\n",
    "        return F.sigmoid(recon_x).view(*x.size()),mu,logvar\n",
    "    \n",
    "    def decode(self,z):\n",
    "        recon_x=F.relu(self.fc2(z))\n",
    "        recon_x=self.fc3(recon_x)\n",
    "        return F.sigmoid(recon_x)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "09858d79",
   "metadata": {},
   "source": [
    "训练"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "77d3ac4c",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "bc1e6a07-6a67-4a6f-b699-33e24badfa60",
   "metadata": {},
   "outputs": [],
   "source": [
    "import csv\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "\n",
    "# 模拟训练数据（实际使用时替换为真实数据）\n",
    "def simulate_training(epochs):\n",
    "    train_loss = [0.9 * np.exp(-0.03 * epoch) + 0.1 * np.random.rand() for epoch in range(epochs)]\n",
    "    val_loss = [0.8 * np.exp(-0.05 * epoch) + 0.1 * np.random.rand() for epoch in range(epochs)]\n",
    "    return train_loss, val_loss\n",
    "\n",
    "# 1. 记录日志到CSV\n",
    "def log_to_csv(filename, train_loss, val_loss):\n",
    "    with open(filename, 'w', newline='') as f:\n",
    "        writer = csv.writer(f)\n",
    "        writer.writerow(['epoch', 'train_loss', 'val_loss'])  # 写入表头\n",
    "        for epoch, (t_loss, v_loss) in enumerate(zip(train_loss, val_loss)):\n",
    "            writer.writerow([epoch, t_loss, v_loss])\n",
    "\n",
    "# 2. 从CSV加载日志并绘图\n",
    "def plot_loss_curve(csv_file):\n",
    "    epochs, train_loss, val_loss = [], [], []\n",
    "    \n",
    "    with open(csv_file, 'r') as f:\n",
    "        reader = csv.reader(f)\n",
    "        next(reader)  # 跳过表头\n",
    "        for row in reader:\n",
    "            epochs.append(int(row[0]))\n",
    "            train_loss.append(float(row[1]))\n",
    "            val_loss.append(float(row[2]))\n",
    "    \n",
    "    plt.figure(figsize=(10, 5))\n",
    "    plt.plot(epochs, train_loss, label='Train Loss', color='blue')\n",
    "    plt.plot(epochs, val_loss, label='Validation Loss', color='red')\n",
    "    plt.xlabel('Epoch')\n",
    "    plt.ylabel('Loss')\n",
    "    plt.title('Training & Validation Loss Curve')\n",
    "    plt.legend()\n",
    "    plt.grid(True)\n",
    "    plt.savefig('loss_curve.png')  # 保存图像\n",
    "    plt.show()\n",
    "    \n",
    "# 记录日志\n",
    "# log_to_csv('training_log.csv', train_loss, val_loss)\n",
    "# print(\"日志已保存到 training_log.csv\")\n",
    "    \n",
    "# 绘制曲线\n",
    "# plot_loss_curve('training_log.csv')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "27e526d9-90c7-4fb9-8359-c0936caefe15",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "加载已存在的模型...\n",
      "模型已从 model.pt 加载\n"
     ]
    }
   ],
   "source": [
    "def train(force_train=False, model_path='model.pt'):\n",
    "    model=VAE(input_size=1*28*28,hidden_size=256,latent_size=20).to(device)\n",
    "    \n",
    "    # 检查是否需要强制训练或模型文件不存在\n",
    "    if force_train or not os.path.exists(model_path):\n",
    "        print(\"开始训练模型...\")\n",
    "        dataloader=torch.utils.data.DataLoader(dataset,batch_size=1024,shuffle=True)\n",
    "        optimizer=torch.optim.AdamW(model.parameters(),lr=1e-2,weight_decay=1e-4)\n",
    "        iters=0\n",
    "        epoch=0\n",
    "        model.train()\n",
    "        total_loss_list = []\n",
    "        recon_loss_list = []\n",
    "        kl_loss_list = []\n",
    "        \n",
    "        \n",
    "        for i in range(200):\n",
    "            for batch_img,batch_labels in dataloader:\n",
    "                batch_img=batch_img.to(device)\n",
    "                batch_labels=batch_labels.to(device)\n",
    "                recon_x,mu,logvar=model(batch_img)\n",
    "                optimizer.zero_grad()\n",
    "                recon_loss=torch.sum(torch.nn.functional.binary_cross_entropy(recon_x,batch_img,reduction='none'),dim=(1,2,3))\n",
    "                kl_loss=-0.5*torch.sum(1+logvar-mu.pow(2)-logvar.exp(),dim=-1)\n",
    "                loss=torch.mean(recon_loss+i/200*kl_loss)\n",
    "                loss.backward()\n",
    "                optimizer.step()\n",
    "                total_loss_list.append(loss.item())\n",
    "                recon_loss_list.append(torch.mean(recon_loss).item())\n",
    "                kl_loss_list.append(torch.mean(kl_loss).item())\n",
    "                iters+=1\n",
    "            torch.save(model.state_dict(),'.model.pt')\n",
    "            os.replace('.model.pt',model_path)\n",
    "            print(f'epoch={epoch} loss={loss.item()}')\n",
    "            epoch+=1\n",
    "        \n",
    "        log_to_csv('total_loss.csv', total_loss, [0])\n",
    "        log_to_csv('recon_loss.csv', recon_loss, [0])\n",
    "        log_to_csv('kl_loss.csv', kl_loss, [0])\n",
    "        print(f\"模型已保存到 {model_path}\")\n",
    "    else:\n",
    "        print(\"加载已存在的模型...\")\n",
    "        model.load_state_dict(torch.load(model_path, map_location=device))\n",
    "        print(f\"模型已从 {model_path} 加载\")\n",
    "    \n",
    "    return model\n",
    "model = train()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "a8d29663",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.image.AxesImage at 0x7f4936b0d810>"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 200x200 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "import random\n",
    "model.eval()\n",
    "with torch.no_grad():\n",
    "    img,_=dataset[random.randint(0,len(dataset))]\n",
    "    recon_x,mu,logvar=model(img.unsqueeze(0).to(device))\n",
    "\n",
    "plt.figure(figsize=(2,2))\n",
    "plt.subplot(1,2,1)\n",
    "plt.imshow(img.view(28,28).numpy())\n",
    "plt.subplot(1,2,2)\n",
    "plt.imshow(recon_x.view(28,28).cpu().numpy())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fa03b0aa-ab99-4af8-98c5-a105088a0dc7",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "8616c476-5d6e-4166-b7db-bc632ba2ce9d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "device(type='cuda')"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "device"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "9a219987",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[ 1.2943, -0.0547,  0.0381,  0.7461,  0.8967,  0.2478, -0.0935, -0.0573,\n",
      "         -0.4801, -1.2355,  0.0029, -1.5667, -0.9186, -0.2618,  1.1339,  1.0358,\n",
      "         -0.0404,  2.1157, -0.2475,  1.7770]], device='cuda:0')\n",
      "tensor([[ 1.2943, -0.0547,  0.0381,  0.7461,  0.8967,  0.5478, -0.0935, -0.0573,\n",
      "         -0.4801, -1.2355,  0.0029, -1.5667, -0.9186, -0.2618,  1.1339,  1.0358,\n",
      "         -0.0404,  2.1157, -0.2475,  1.7770]], device='cuda:0')\n",
      "tensor([[ 1.2943, -0.0547,  0.0381,  0.7461,  0.8967,  0.8478, -0.0935, -0.0573,\n",
      "         -0.4801, -1.2355,  0.0029, -1.5667, -0.9186, -0.2618,  1.1339,  1.0358,\n",
      "         -0.0404,  2.1157, -0.2475,  1.7770]], device='cuda:0')\n",
      "tensor([[ 1.2943, -0.0547,  0.0381,  0.7461,  0.8967,  1.1478, -0.0935, -0.0573,\n",
      "         -0.4801, -1.2355,  0.0029, -1.5667, -0.9186, -0.2618,  1.1339,  1.0358,\n",
      "         -0.0404,  2.1157, -0.2475,  1.7770]], device='cuda:0')\n",
      "tensor([[ 1.2943, -0.0547,  0.0381,  0.7461,  0.8967,  1.4478, -0.0935, -0.0573,\n",
      "         -0.4801, -1.2355,  0.0029, -1.5667, -0.9186, -0.2618,  1.1339,  1.0358,\n",
      "         -0.0404,  2.1157, -0.2475,  1.7770]], device='cuda:0')\n",
      "tensor([[ 1.2943, -0.0547,  0.0381,  0.7461,  0.8967,  1.7478, -0.0935, -0.0573,\n",
      "         -0.4801, -1.2355,  0.0029, -1.5667, -0.9186, -0.2618,  1.1339,  1.0358,\n",
      "         -0.0404,  2.1157, -0.2475,  1.7770]], device='cuda:0')\n",
      "tensor([[ 1.2943, -0.0547,  0.0381,  0.7461,  0.8967,  2.0478, -0.0935, -0.0573,\n",
      "         -0.4801, -1.2355,  0.0029, -1.5667, -0.9186, -0.2618,  1.1339,  1.0358,\n",
      "         -0.0404,  2.1157, -0.2475,  1.7770]], device='cuda:0')\n",
      "tensor([[ 1.2943, -0.0547,  0.0381,  0.7461,  0.8967,  2.3478, -0.0935, -0.0573,\n",
      "         -0.4801, -1.2355,  0.0029, -1.5667, -0.9186, -0.2618,  1.1339,  1.0358,\n",
      "         -0.0404,  2.1157, -0.2475,  1.7770]], device='cuda:0')\n",
      "tensor([[ 1.2943, -0.0547,  0.0381,  0.7461,  0.8967,  2.6478, -0.0935, -0.0573,\n",
      "         -0.4801, -1.2355,  0.0029, -1.5667, -0.9186, -0.2618,  1.1339,  1.0358,\n",
      "         -0.0404,  2.1157, -0.2475,  1.7770]], device='cuda:0')\n",
      "tensor([[ 1.2943e+00, -5.4734e-02,  3.8058e-02,  7.4609e-01,  8.9675e-01,\n",
      "          2.9478e+00, -9.3505e-02, -5.7313e-02, -4.8008e-01, -1.2355e+00,\n",
      "          2.9029e-03, -1.5667e+00, -9.1858e-01, -2.6183e-01,  1.1339e+00,\n",
      "          1.0358e+00, -4.0399e-02,  2.1157e+00, -2.4750e-01,  1.7770e+00]],\n",
      "       device='cuda:0')\n",
      "tensor([[ 1.2943e+00, -5.4734e-02,  3.8058e-02,  7.4609e-01,  8.9675e-01,\n",
      "          3.2478e+00, -9.3505e-02, -5.7313e-02, -4.8008e-01, -1.2355e+00,\n",
      "          2.9029e-03, -1.5667e+00, -9.1858e-01, -2.6183e-01,  1.1339e+00,\n",
      "          1.0358e+00, -4.0399e-02,  2.1157e+00, -2.4750e-01,  1.7770e+00]],\n",
      "       device='cuda:0')\n",
      "tensor([[ 1.2943e+00, -5.4734e-02,  3.8058e-02,  7.4609e-01,  8.9675e-01,\n",
      "          3.5478e+00, -9.3505e-02, -5.7313e-02, -4.8008e-01, -1.2355e+00,\n",
      "          2.9029e-03, -1.5667e+00, -9.1858e-01, -2.6183e-01,  1.1339e+00,\n",
      "          1.0358e+00, -4.0399e-02,  2.1157e+00, -2.4750e-01,  1.7770e+00]],\n",
      "       device='cuda:0')\n",
      "tensor([[ 1.2943e+00, -5.4734e-02,  3.8058e-02,  7.4609e-01,  8.9675e-01,\n",
      "          3.8478e+00, -9.3505e-02, -5.7313e-02, -4.8008e-01, -1.2355e+00,\n",
      "          2.9029e-03, -1.5667e+00, -9.1858e-01, -2.6183e-01,  1.1339e+00,\n",
      "          1.0358e+00, -4.0399e-02,  2.1157e+00, -2.4750e-01,  1.7770e+00]],\n",
      "       device='cuda:0')\n",
      "tensor([[ 1.2943e+00, -5.4734e-02,  3.8058e-02,  7.4609e-01,  8.9675e-01,\n",
      "          4.1478e+00, -9.3505e-02, -5.7313e-02, -4.8008e-01, -1.2355e+00,\n",
      "          2.9029e-03, -1.5667e+00, -9.1858e-01, -2.6183e-01,  1.1339e+00,\n",
      "          1.0358e+00, -4.0399e-02,  2.1157e+00, -2.4750e-01,  1.7770e+00]],\n",
      "       device='cuda:0')\n",
      "tensor([[ 1.2943e+00, -5.4734e-02,  3.8058e-02,  7.4609e-01,  8.9675e-01,\n",
      "          4.4478e+00, -9.3505e-02, -5.7313e-02, -4.8008e-01, -1.2355e+00,\n",
      "          2.9029e-03, -1.5667e+00, -9.1858e-01, -2.6183e-01,  1.1339e+00,\n",
      "          1.0358e+00, -4.0399e-02,  2.1157e+00, -2.4750e-01,  1.7770e+00]],\n",
      "       device='cuda:0')\n",
      "tensor([[ 1.2943e+00, -5.4734e-02,  3.8058e-02,  7.4609e-01,  8.9675e-01,\n",
      "          4.7478e+00, -9.3505e-02, -5.7313e-02, -4.8008e-01, -1.2355e+00,\n",
      "          2.9029e-03, -1.5667e+00, -9.1858e-01, -2.6183e-01,  1.1339e+00,\n",
      "          1.0358e+00, -4.0399e-02,  2.1157e+00, -2.4750e-01,  1.7770e+00]],\n",
      "       device='cuda:0')\n",
      "tensor([[ 1.2943e+00, -5.4734e-02,  3.8058e-02,  7.4609e-01,  8.9675e-01,\n",
      "          5.0478e+00, -9.3505e-02, -5.7313e-02, -4.8008e-01, -1.2355e+00,\n",
      "          2.9029e-03, -1.5667e+00, -9.1858e-01, -2.6183e-01,  1.1339e+00,\n",
      "          1.0358e+00, -4.0399e-02,  2.1157e+00, -2.4750e-01,  1.7770e+00]],\n",
      "       device='cuda:0')\n",
      "tensor([[ 1.2943e+00, -5.4734e-02,  3.8058e-02,  7.4609e-01,  8.9675e-01,\n",
      "          5.3478e+00, -9.3505e-02, -5.7313e-02, -4.8008e-01, -1.2355e+00,\n",
      "          2.9029e-03, -1.5667e+00, -9.1858e-01, -2.6183e-01,  1.1339e+00,\n",
      "          1.0358e+00, -4.0399e-02,  2.1157e+00, -2.4750e-01,  1.7770e+00]],\n",
      "       device='cuda:0')\n",
      "tensor([[ 1.2943e+00, -5.4734e-02,  3.8058e-02,  7.4609e-01,  8.9675e-01,\n",
      "          5.6478e+00, -9.3505e-02, -5.7313e-02, -4.8008e-01, -1.2355e+00,\n",
      "          2.9029e-03, -1.5667e+00, -9.1858e-01, -2.6183e-01,  1.1339e+00,\n",
      "          1.0358e+00, -4.0399e-02,  2.1157e+00, -2.4750e-01,  1.7770e+00]],\n",
      "       device='cuda:0')\n",
      "tensor([[ 1.2943e+00, -5.4734e-02,  3.8058e-02,  7.4609e-01,  8.9675e-01,\n",
      "          5.9478e+00, -9.3505e-02, -5.7313e-02, -4.8008e-01, -1.2355e+00,\n",
      "          2.9029e-03, -1.5667e+00, -9.1858e-01, -2.6183e-01,  1.1339e+00,\n",
      "          1.0358e+00, -4.0399e-02,  2.1157e+00, -2.4750e-01,  1.7770e+00]],\n",
      "       device='cuda:0')\n"
     ]
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 200x500 with 20 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "\n",
    "model.eval()\n",
    "latent=torch.randn(1,20)\n",
    "plt.figure(figsize=(2,5))\n",
    "with torch.no_grad():\n",
    "    for i in range(20):\n",
    "        plt.subplot(4,5,i+1)\n",
    "        latent[0][5] = (i/20)\n",
    "        dev_latent = latent.to(device)\n",
    "        print(dev_latent)\n",
    "        recon_x=model.decode(dev_latent)\n",
    "        plt.imshow(recon_x.view(28,28).cpu().numpy())\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5d030acb-1e61-43bf-bd70-132f09111f8d",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.13.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
